package com.breeze.breezelive.play;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;

import java.io.IOException;
import java.nio.ByteBuffer;

public class AudioPlayerThread extends Thread {
    private static final int TIMEOUT_MS = 10000;
    private AudioTrack mAudioTrack;
    private MediaExtractor mExtractor;
    private MediaCodec mMediaCodec;
    private MediaCodec.BufferInfo mBufferInfo;
    private String mPath;

    public AudioPlayerThread(String path) {
        this.mPath = path;
    }

    public boolean prepare() {
        try {
            mExtractor = new MediaExtractor();
            mBufferInfo = new MediaCodec.BufferInfo();
            mExtractor.setDataSource(mPath);
            MediaFormat mediaFormat = null;
            for (int i = 0; i < mExtractor.getTrackCount(); i++) {
                mediaFormat = mExtractor.getTrackFormat(i);
                String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
                if (mime.startsWith(MediaFormat.MIMETYPE_AUDIO_AAC)) {
                    mExtractor.selectTrack(i);
                    break;
                }
            }
            int sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
            int channelConfig = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
            int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, AudioFormat.ENCODING_PCM_16BIT);
            minBufferSize = Math.max(minBufferSize, 1024);
            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, channelConfig, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
            mAudioTrack.play();
            mMediaCodec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
            mMediaCodec.configure(mediaFormat, null, null, 0);
            mMediaCodec.start();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public void run() {
        boolean isFinish = false;
        while (!isFinish) {
            int inputIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_MS);
            if (inputIndex < 0) {
                break;
            }
            ByteBuffer inputBuffer = mMediaCodec.getInputBuffer(inputIndex);
            inputBuffer.clear();
            int sampleSize = mExtractor.readSampleData(inputBuffer, 0);
            if (sampleSize > 0) {
                mMediaCodec.queueInputBuffer(inputIndex, 0, sampleSize, 0, 0);
                mExtractor.advance();
            } else {
                isFinish = true;
            }
            int outputIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_MS);
            ByteBuffer outputBuffer;
            byte[] chunkPCM;
            while (outputIndex >= 0) {
                outputBuffer = mMediaCodec.getOutputBuffer(outputIndex);
                chunkPCM = new byte[mBufferInfo.size];
                outputBuffer.get(chunkPCM); // 将 Buffer内的数据取出到字节数组中
                outputBuffer.clear(); // 数据取出后一定记得清空此 Buffer MediaCodec 是循环使用这些 Buffer 的，不清空下次会得到同样的数据
                mAudioTrack.write(chunkPCM, 0, mBufferInfo.size);
                mMediaCodec.releaseOutputBuffer(outputIndex, false); // 此操作一定要做，不然 MediaCodec 用完所有的 Buffer 后将不能向外输出数据
                outputIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_MS);
            }
        }
        release();
    }

    private void release() {
        if (mMediaCodec != null) {
            mMediaCodec.stop();
            mMediaCodec.release();
            mMediaCodec = null;
        }

        if (mExtractor != null) {
            mExtractor.release();
            mExtractor = null;
        }

        if (mAudioTrack != null) {
            mAudioTrack.stop();
            mAudioTrack.release();
            mAudioTrack = null;
        }
    }
}